package com.taichuan.selfcheck.crash;

import android.content.Context;
import android.os.Environment;

import com.orhanobut.logger.Logger;
import com.taichuan.tcutils.common.FileUtils;
import com.taichuan.tcutils.common.SystemInfoUtils;
import com.taichuan.tcutils.common.TimeUtils;
import com.tencent.bugly.crashreport.CrashReport;
import java.io.File;
import java.util.Map;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by CamelLuo on 2018/7/6.
 */
public class TcCrashCallback extends CrashReport.CrashHandleCallback {
    private static final String TAG = TcCrashCallback.class.getSimpleName();
    private static final String CRASH_REPORTER_EXTENSION = ".cr";
    private Context mContext;
    private final String softwareVersion;
    private final String systemVersion;

    public TcCrashCallback(Context mContext) {
        this.mContext = mContext;
        softwareVersion = SystemInfoUtils.getSoftwareVersion(mContext.getApplicationContext()) +
                " | VersionCode: " + SystemInfoUtils.getSoftwareVersionCode(mContext.getApplicationContext());
        systemVersion = SystemInfoUtils.getSystemVersion();
    }

    @Override
    public synchronized Map<String, String> onCrashHandleStart(int crashType, String errorType, String errorMessage, String errorStack) {
        Logger.t(TAG).e("onCrashHandleStart  错误类型：  " + crashType + "  错误的类型名： " + errorType + "\n" +
                "错误信息：  " + errorMessage + "\n" + "  错误的堆栈：  " + errorStack);
        saveCrashInfo(crashType, errorType, errorMessage, errorStack);
        return super.onCrashHandleStart(crashType, errorType, errorMessage, errorStack);
    }

    @Override
    public synchronized byte[] onCrashHandleStart2GetExtraDatas(int crashType, String errorType, String errorMessage, String errorStack) {
        return super.onCrashHandleStart2GetExtraDatas(crashType, errorType, errorMessage, errorStack);
    }

    /**
     * 定义一个方法用于保存Crash信息到本地
     * @param crashType
     * @param errorType
     * @param errorMessage
     * @param errorStack
     */
    private void saveCrashInfo(final int crashType, final String errorType, final String errorMessage, final String errorStack) {
        Observable.just("")
                .observeOn(Schedulers.io())
                .map(new Function<String, Boolean>() {

                    @Override
                    public Boolean apply(String s) throws Exception {
                        //格式化错误Crash信息
                        StringBuffer errorContent = new StringBuffer();
                        String currentTime = TimeUtils.getCurrentTime();
                        long timestamp = System.currentTimeMillis();
                        errorContent.append("-----------------------------------TC-自检程序-Crash信息-Start---------------------------------------" + "\n" + "\n");
                        errorContent.append("软件版本：  " + softwareVersion + "\n");
                        errorContent.append("系统版本：  " + systemVersion + "\n");
                        errorContent.append("发生时间：  " + currentTime + "\n");
                        errorContent.append("错误类型：  " + getCrashTypeName(crashType) + "\n");
                        errorContent.append("错误的类型名:  " + errorType +"\n");
                        errorContent.append("错误信息:  "  +"\n" + errorMessage +"\n");
                        errorContent.append("错误的堆栈:  "  +"\n" + errorStack +"\n");
                        errorContent.append("\n" + "-----------------------------------TC-自检程序-Crash信息-End---------------------------------------");
                        //将Crash信息保存到本地
                        File file = new File(getErrorRootPath(),"crash-" + timestamp + CRASH_REPORTER_EXTENSION);
                        boolean isSucess = FileUtils.writeFile(file, errorContent.toString(), false);
                        return isSucess;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean isSucess) throws Exception {
                        Logger.t(TAG).e("Crash信息保存状态：  " + isSucess);
//                        Toast.makeText(mContext,"程序遇到应用层崩溃！",Toast.LENGTH_LONG);
                    }
                });
    }

    /**
     * 错误日志根目录
     */
    public static String getErrorRootPath() {
        return Environment.getExternalStorageDirectory().getPath() + "/tcSelfCheck/error/";
    }

    private String getCrashTypeName(int crashType){
        switch (crashType){
            case CRASHTYPE_JAVA_CRASH:{
                return "Java crash";
            }
            case CRASHTYPE_JAVA_CATCH:{
                return "Java caught exception";
            }
            case CRASHTYPE_NATIVE:{
                return "Native crash";
            }
            case CRASHTYPE_U3D:{
                return "Unity error";
            }
            case CRASHTYPE_ANR:{
                return "Java crash";
            }
            case CRASHTYPE_COCOS2DX_JS:{
                return "Cocos JS error";
            }
            case CRASHTYPE_COCOS2DX_LUA:{
                return "Cocos Lua error";
            }
            default:{
                return "unknown error";
            }
        }
    }
}
